﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using CrawlerCore;
using HtmlAgilityPack;

namespace WCrawlerLib.WebSession.phpBB
{
    public class PhpBBForumSession : ForumSessionBase
    {
        public string sid
        {
            get
            {
                string value = "";
                try
                {
                    foreach (Cookie cook in Cookies)
                    {
                        if (cook.Name.Contains("sid"))
                        {
                            value = cook.Value;
                            break;
                        }
                    }
                    //HtmlNode node = _htmlDoc.DocumentNode.SelectSingleNode(".//input[@type='hidden' and @name='loggedinuser']");
                    //if (node != null)
                    //    value = node.Attributes["value"].Value;
                }
                catch
                {
                }
                return value;
            }
        }

        public override bool CheckLoginStatus()
        {
            bool loginStatus = false;
            string content = HtmlDoc.DocumentNode.InnerHtml.ToLower();
            List<string> key = new List<string>();

            string pattern = @"(thank you|successful(ly|) logged in|log out|" + ObjForum.Account.UserName + ")";

            Regex r = new Regex(pattern);
            MatchCollection m = r.Matches(content);

            //If count > 1 successfully log in
            if (m.Count >= 1)
            {
                loginStatus = true;
            }
            return loginStatus;
        }

        /// <summary>
        /// Get user id
        /// </summary>
        /// <param name="forumUrl"></param>
        /// <param name="userName"></param>
        /// <returns></returns>
        public override int GetAccountId()
        {
            //*********************************************************************************
            //Get User Id
            //*********************************************************************************
            int userId = -1;
            string profileUrl = ObjForum.ForumUrl + "/" + "ucp.php";
            HtmlDocument doc = Get(profileUrl);
            string htmlContent = HttpUtility.HtmlDecode(doc.DocumentNode.InnerHtml);
            string pattern = @"search\.php\?author_id=(?<value>[0-9]+)";
            Regex r = new Regex(pattern);
            Match m = r.Match(htmlContent);
            if (m.Success)
            {
                userId = int.Parse(m.Result("${value}"));
            }
            return userId;
        }

        public override string InitLoginParams(string postParams, params string[] pars)
        {
            //_postParams = "username=" + username
            //        + "&password=" + password
            //        + "&autologin=" + "on"
            //        + "&sid=" + ""
            //        + "&redirect="
            //        + "&login=" + "Login";

            ParamDict = new Dictionary<string, string>();
            ParamDict.Add("[username]", pars[0]);
            ParamDict.Add("[password]", pars[1]);
            ParamDict.Add("[login]", "Login");
            ParamDict.Add("[autologin]", "on");
            //for phpbb2
            ParamDict.Add("[sid]", "");
            ParamDict.Add("[redirect]", "");
            InitGeneralPostParams(postParams, pars);
            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override string InitEditPostParams(string postParams, params string[] pars)
        {
            ParamDict.Add("[icon]", pars[2]);
            ParamDict.Add("[subject]", pars[0]);
            //ParamDict.Add("[addbbcode20]", "100");
            ParamDict.Add("[message]", pars[1].Replace("&", "%26"));
            //ParamDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
            ParamDict.Add("[edit_post_message_checksum]", HtmlDoc.GetValueInInputTag("hidden", "name", "edit_post_message_checksum"));
            ParamDict.Add("[edit_post_subject_checksum]", HtmlDoc.GetValueInInputTag("hidden", "name", "edit_post_subject_checksum"));
            ParamDict.Add("[post]", "Submit");
            //ParamDict.Add("[attach_sig]", "on");
            //ParamDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
            //ParamDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));
            InitGeneralPostParams(postParams, pars);
            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override string InitNewReplyParams(string postParams, params string[] pars)
        {
            ParamDict = new Dictionary<string, string>();

            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override string InitNewThreadParams(string postParams, params string[] pars)
        {
            ParamDict = new Dictionary<string, string>();
            ParamDict.Add("[icon]", pars[3]);
            ParamDict.Add("[subject]", pars[0]);
            //ParamDict.Add("[addbbcode20]", "100");
            ParamDict.Add("[message]", pars[1].Replace("&", "%26"));
            //ParamDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
            ParamDict.Add("[post]", "Submit");
            //ParamDict.Add("[attach_sig]", "on");
            //ParamDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
            //ParamDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));

            InitGeneralPostParams(postParams, pars);
            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override void InitGeneralPostParams(string postParams, params string[] pars)
        {
            ParamDict.Add("[addbbcode20]", "100");
            ParamDict.Add("[lastclick]", HtmlDoc.GetValueInInputTag("hidden", "name", "lastclick"));
            ParamDict.Add("[attach_sig]", "on");
            ParamDict.Add("[creation_time]", HtmlDoc.GetValueInInputTag("hidden", "name", "creation_time"));
            ParamDict.Add("[form_token]", HtmlDoc.GetValueInInputTag("hidden", "name", "form_token"));
        }

        public override void PostNewThread(string subject, string message, string fId, string iconId, string tagList, string prefixId)
        {
            string newThreadUrl = ObjForum.NewThreadUrlPattern.Replace("[fid]", fId.ToString());
            //get post url for GET request
            newThreadUrl = GeneralClass.GetFullUrl(ObjForum.ForumUrl, newThreadUrl);
            Get(newThreadUrl);

            //Get POST Params 
            _postParams = InitNewThreadParams(ObjForum.NewThreadParams, subject, message, fId, iconId, tagList);

            //get post url for POST request
            newThreadUrl = string.Format("{0}/{1}/&sid={2}", ObjForum.ForumUrl, newThreadUrl, sid);
            Post(newThreadUrl);
        }

        public override bool PostNewReply(string topicUrl, string newReplyUrl, string postParams, string message)
        {
            throw new NotImplementedException();
        }

        public override bool PostEdit(string forumUrl, string topicUrl, string postId, string editParams, string subject, string message, string updateReason, string icon)
        {
            throw new NotImplementedException();
        }
    }

    public class phpBB2ForumSession : PhpBBForumSession
    {
        public override string ConvertHtmlContent(PostDetail objPostDetail)
        {
            string fullHtmlContent = base.ConvertHtmlContent(objPostDetail);

            Regex r = new Regex("\\[SIZE\\=(\"|)(?<size>[0-9]+)(\"|)\\]");
            Match m = r.Match(fullHtmlContent);
            while (m.Success)
            {
                int size = int.Parse(m.Result("${size}"));
                switch (size)
                {
                    case 1:
                        fullHtmlContent = fullHtmlContent.Replace(m.Value, "[SIZE=7]");
                        break;
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                        fullHtmlContent = fullHtmlContent.Replace(m.Value, "[SIZE=18]");
                        break;
                    case 6:
                    case 7:
                        fullHtmlContent = fullHtmlContent.Replace(m.Value, "[SIZE=24]");
                        break;
                    default:
                        break;
                }
                m = m.NextMatch();
            }
            return fullHtmlContent;
        }
    }

    public class phpBB3ForumSession : PhpBBForumSession
    {
        public override string ConvertHtmlContent(PostDetail objPostDetail)
        {
            string fullHtmlContent = base.ConvertHtmlContent(objPostDetail);
            
            Regex r = new Regex("\\[SIZE\\=(\"|)(?<size>[0-9]+)(\"|)\\]");
            Match m = r.Match(fullHtmlContent);
            while (m.Success)
            {
                int size = int.Parse(m.Result("${size}"));
                switch (size)
                {
                    case 1:
                        fullHtmlContent = fullHtmlContent.Replace(m.Value, "[SIZE=50]");
                        break;
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                        fullHtmlContent = fullHtmlContent.Replace(m.Value, "[SIZE=150]");
                        break;
                    case 6:
                    case 7:
                        fullHtmlContent = fullHtmlContent.Replace(m.Value, "[SIZE=200]");
                        break;
                    default:
                        break;
                }
                m = m.NextMatch();
            }
            
            return fullHtmlContent;
        }
    }
}
